﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Types;

namespace Client
{
    class ClientManager
    {
        private static ClientManager instance;
        private ClientConnectionManager clientConnnectionManager;
        public string username { get; private set; }

        public event ShowErrorMessage showErrorMessage;
        public delegate void ShowErrorMessage(string message);

        public event ShowMainForm showMainForm;
        public delegate void ShowMainForm(UserType user);

        public event CloseClient closeClient;
        public delegate void CloseClient();

        public event UpdateCourseList updateCourseList;
        public delegate void UpdateCourseList(List<CourseType> courseList);

        public event UpdateQuestionList updateQuestionList;
        public delegate void UpdateQuestionList(List<QuestionType> questionList);

        public event UpdateAnswerList updateAnswerList;
        public delegate void UpdateAnswerList(List<AnswerType> answerList);

        public event AddQuestionDelegate addQuestion;
        public delegate void AddQuestionDelegate(string summary);

        public event DeleteQuestionDelegate deleteQuestion;
        public delegate void DeleteQuestionDelegate(string summary);

        public event AddAnswerDelegate addAnswer;
        public delegate void AddAnswerDelegate(string summary);

        public event UpdateSearchList updateSearchList;
        public delegate void UpdateSearchList(List<object> searchList);

        public event UpdateFileContent updateFileContent;
        public delegate void UpdateFileContent(string fileContent);

        public event UpdateCourseName updateCourseName;
        public delegate void UpdateCourseName(string courseName);

        public event UpdateQuestionSummary updateQuestionSummary;
        public delegate void UpdateQuestionSummary(string questionSummary);

        public static ClientManager Instance
        {
            get
            {
                if (instance == null)
                {
                    instance = new ClientManager();
                }
                return instance;
            }
        }

        private ClientManager()
        {
            clientConnnectionManager = new ClientConnectionManager();
        }


        public void HandleReadyRequest(object data)
        {
            Request request = data as Request;

            switch (request.requestType)
            {
                case RequestId.Login:
                    HandleLogin(request);
                    break;
                case RequestId.Logout:
                    HandleLogout(request);
                    break;
                case RequestId.ServerClosed:
                    HandleServerClosedNotifyUser(request);
                    break;
                case RequestId.Subscribe:
                    HandleSubscribe(request);
                    break;
                case RequestId.GetCourseList:
                    HandleGetCourseList(request);
                    break;
                case RequestId.GetQuestionList:
                    HandleGetQuestionList(request);
                    break;
                case RequestId.GetMyQuestions:
                    HandleGetMyQuestionList(request);
                    break;
                case RequestId.GetAnswerList:
                    HandleGetAnswerList(request);
                    break;
                case RequestId.AddQuestion:
                    HandleAddQuestion(request);
                    break;
                case RequestId.DeleteQuestion:
                    HandleDeleteQuestion(request);
                    break;
                case RequestId.AddAnswer:
                    HandleAddAnswer(request);
                    break;
                case RequestId.Search:
                    HandleSearch(request);
                    break;
                case RequestId.GetFileContent:
                    HandleGetFileContent(request);
                    break;
                case RequestId.GetCourseName:
                    HandleGetCourseName(request);
                    break;
                case RequestId.GetQuestionSummary:
                    HandleGetQuestionSummary(request);
                    break;
            }
        }

        private void HandleLogin(Request request)
        {
            if (request.operationResult)
            {
                UserType user = request.objectType as UserType;
                showMainForm(user);
            }
            else
            {
                ErrorMessage errorMessage = request.objectType as ErrorMessage;
                showErrorMessage(errorMessage.message);
            }
        }

        private void HandleServerClosedNotifyUser(Request request)
        {
            UserType user = request.objectType as UserType;
            closeClient();
        }

        private void HandleLogout(Request request)
        {
            if (request.operationResult)
            {
                UserType user = request.objectType as UserType;
            }
            else
            {
                ErrorMessage errorMessage = request.objectType as ErrorMessage;
                showErrorMessage(errorMessage.message);
            }
        }

        private void HandleSubscribe(Request request)
        {
            if (request.operationResult)
            {
                UserType user = request.objectType as UserType;
            }
            else
            {
                ErrorMessage errorMsg = request.objectType as ErrorMessage;
                showErrorMessage(errorMsg.message);
            }
        }

        private void HandleGetCourseList(Request request)
        {
            if (request.operationResult)
            {
                List<CourseType> courseList = request.objectType as List<CourseType>;
                updateCourseList(courseList);
            }
            else
            {
                ErrorMessage errorMsg = request.objectType as ErrorMessage;
                showErrorMessage(errorMsg.message);
            }
        }

        private void HandleGetQuestionList(Request request)
        {
            if (request.operationResult)
            {
                List<QuestionType> questionList = request.objectType as List<QuestionType>;
                updateQuestionList(questionList);
            }
            else
            {
                ErrorMessage errorMsg = request.objectType as ErrorMessage;
                showErrorMessage(errorMsg.message);
            }
        }

        private void HandleGetMyQuestionList(Request request)
        {
            if (request.operationResult)
            {
                List<QuestionType> questionList = request.objectType as List<QuestionType>;
                updateQuestionList(questionList);
            }
            else
            {
                ErrorMessage errorMsg = request.objectType as ErrorMessage;
                showErrorMessage(errorMsg.message);
            }
        }

        private void HandleGetAnswerList(Request request)
        {
            if (request.operationResult)
            {
                List<AnswerType> answerList = request.objectType as List<AnswerType>;
                updateAnswerList(answerList);
            }
            else
            {
                ErrorMessage errorMsg = request.objectType as ErrorMessage;
                showErrorMessage(errorMsg.message);
            }
        }

        private void HandleAddQuestion(Request request)
        {
            if (request.operationResult)
            {
                QuestionType question = request.objectType as QuestionType;
                addQuestion(question.summary);
            }
            else
            {
                ErrorMessage errorMsg = request.objectType as ErrorMessage;
                showErrorMessage(errorMsg.message);
            }
        }

        private void HandleDeleteQuestion(Request request)
        {
            if (request.operationResult)
            {
                string questionSummary = request.objectType as string;
                deleteQuestion(questionSummary);
            }
            else
            {
                ErrorMessage errorMsg = request.objectType as ErrorMessage;
                showErrorMessage(errorMsg.message);
            }
        }

        private void HandleAddAnswer(Request request)
        {
            if (request.operationResult)
            {
                AnswerType answer = request.objectType as AnswerType;
                addAnswer(answer.summary);
            }
            else
            {
                ErrorMessage errorMsg = request.objectType as ErrorMessage;
                showErrorMessage(errorMsg.message);
            }
        }

        private void HandleSearch(Request request)
        {
            if (request.operationResult)
            {
                List<object> searchList = request.objectType as List<object>;
                updateSearchList(searchList);
            }
            else
            {
                ErrorMessage errorMsg = request.objectType as ErrorMessage;
                showErrorMessage(errorMsg.message);
            }
        }

        private void HandleGetFileContent(Request request)
        {
            if (request.operationResult)
            {
                string fileContent = request.objectType as string;
                updateFileContent(fileContent);
            }
            else
            {
                ErrorMessage errorMsg = request.objectType as ErrorMessage;
                showErrorMessage(errorMsg.message);
            }
        }

        private void HandleGetCourseName(Request request)
        {
            if (request.operationResult)
            {
                string courseName = request.objectType as string;
                updateCourseName(courseName);
            }
            else
            {
                ErrorMessage errorMsg = request.objectType as ErrorMessage;
                showErrorMessage(errorMsg.message);
            }
        }

        private void HandleGetQuestionSummary(Request request)
        {
            if (request.operationResult)
            {
                string questionSummary = request.objectType as string;
                updateQuestionSummary(questionSummary);
            }
            else
            {
                ErrorMessage errorMsg = request.objectType as ErrorMessage;
                showErrorMessage(errorMsg.message);
            }
        }

        public void Connect()
        {
            try
            {
                clientConnnectionManager.ConnectToServer();
                clientConnnectionManager.StartToListen();
            }
            catch (ConnectionException)
            {
                throw;
            }
        }

        public void LoginUser(string username, string password)
        {
            Request request = new Request(RequestId.Login, new UserType(username, password));
            try
            {
                clientConnnectionManager.SendData(request);
            }
            catch (ConnectionException)
            {
                throw;
            }
        }

        public void LogoutUser(string username)
        {
            Request request = new Request(RequestId.Logout, new UserType(username, null));
            try
            {
                clientConnnectionManager.SendData(request);
            }
            catch (ConnectionException)
            {
                throw;
            }
        }

        public void SubscribeNewUser(string username, string password, string firstName, string lastName, string id, int year)
        {
            Request request = new Request(RequestId.Subscribe, new UserType(username, password, firstName, lastName, id, year));
            try
            {
                clientConnnectionManager.SendData(request);
            }
            catch (ConnectionException)
            {
                throw;
            }
        }

        public void GetCourseList(string username)
        {
            Request request = new Request(RequestId.GetCourseList, username);
            try
            {
                clientConnnectionManager.SendData(request);
            }
            catch (ConnectionException)
            {
                throw;
            }
        }

        public void GetQuestionList(string username)
        {
            Request request = new Request(RequestId.GetQuestionList, username);
            try
            {
                clientConnnectionManager.SendData(request);
            }
            catch (ConnectionException)
            {
                throw;
            }
        }

        public void GetMyQuestionList(string username)
        {
            Request request = new Request(RequestId.GetMyQuestions, username);
            try
            {
                clientConnnectionManager.SendData(request);
            }
            catch (ConnectionException)
            {
                throw;
            }
        }

        public void GetAnswerList(QuestionType question)
        {
            Request request = new Request(RequestId.GetAnswerList, question);
            try
            {
                clientConnnectionManager.SendData(request);
            }
            catch (ConnectionException)
            {
                throw;
            }
        }

        public void AddNewQuestion(int id, string summary, string filePath, string creator, int courseId)
        {
            Request request = new Request(RequestId.AddQuestion, new QuestionType(id, summary, filePath, creator, courseId));
            try
            {
                clientConnnectionManager.SendData(request);
            }
            catch (ConnectionException)
            {
                throw;
            }
        }

        public void DeleteQuestion(QuestionType question)
        {
            Request request = new Request(RequestId.DeleteQuestion, question);
            try
            {
                clientConnnectionManager.SendData(request);
            }
            catch (ConnectionException)
            {
                throw;
            }
        }

        public void AddNewAnswer(int id, string summary, int questionId, string filePath)
        {
            Request request = new Request(RequestId.AddAnswer, new AnswerType(id, summary, questionId, filePath));
            try
            {
                clientConnnectionManager.SendData(request);
            }
            catch (ConnectionException)
            {
                throw;
            }
        }

        public void GetQuestionId(string questionSummary)
        {
            Request request = new Request(RequestId.GetQuestionId, questionSummary);
            try
            {
                clientConnnectionManager.SendData(request);
            }
            catch (ConnectionException)
            {
                throw;
            }
        }

        public void Search(string searchCriteria, string username)
        {
            Request request = new Request(RequestId.Search, new SearchType(username, searchCriteria));
            try
            {
                clientConnnectionManager.SendData(request);
            }
            catch (ConnectionException)
            {
                throw;
            }
        }

        public void SearchBetweenDates(string searchCriteria, string username, DateTime startDate, DateTime endDate)
        {
            Request request = new Request(RequestId.Search, new SearchType(username, searchCriteria, startDate, endDate));
            try
            {
                clientConnnectionManager.SendData(request);
            }
            catch (ConnectionException)
            {
                throw;
            }
        }

        public void GetFileContent(object obj)
        {
            Request request = new Request(RequestId.GetFileContent, obj);
            try
            {
                clientConnnectionManager.SendData(request);
            }
            catch (ConnectionException)
            {
                throw;
            }
        }

        public void GetCourseName(object obj)
        {
            Request request = new Request(RequestId.GetCourseName, obj);
            try
            {
                clientConnnectionManager.SendData(request);
            }
            catch (ConnectionException)
            {
                throw;
            }
        }

        public void GetQuestionSummary(AnswerType answer)
        {
            Request request = new Request(RequestId.GetQuestionSummary, answer);
            try
            {
                clientConnnectionManager.SendData(request);
            }
            catch (ConnectionException)
            {
                throw;
            }
        }
    }
}
